﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FortuneUniverse.Fortune.Algorithms;

namespace FortuneUniverse.Fortune.Dyson
{
  public class PlanetAlgorithm7 : PlanetAlgorithm
  {
    public override void GenerateTerrain(double modX, double modY)
    {
      double num = 0.008;
      double num2 = 0.01;
      double num3 = 0.01;
      double num4 = 3.0;
      double num5 = -2.4;
      double num6 = 0.9;
      double num7 = 0.5;
      double num8 = 2.5;
      double num9 = 0.3;
      URandom1 urandom1 = new URandom1(this.planet.seed);
      int seed1 = urandom1.Next();
      int seed2 = urandom1.Next();
      SimplexNoise simplexNoise = new SimplexNoise(seed1);
      SimplexNoise simplexNoise2 = new SimplexNoise(seed2);
      PlanetRawData data = this.planet.data;
      Parallel.For(0, data.dataLength, (Action<int>) (i =>
      {
        double num1 = (double) data.vertices[i].x * (double) this.planet.radius;
        double num10 = (double) data.vertices[i].y * (double) this.planet.radius;
        double num11 = (double) data.vertices[i].z * (double) this.planet.radius;
        double num12 = simplexNoise.Noise3DFBM(num1 * num, num10 * num2, num11 * num3, 6) * num4 + num5;
        double num13 = simplexNoise2.Noise3DFBM(num1 * (1.0 / 400.0), num10 * (1.0 / 400.0), num11 * (1.0 / 400.0), 3) * num4 * num6 + num7;
        double num14 = num13 <= 0.0 ? num13 : num13 * 0.5;
        double num15 = num12 + num14;
        double f = num15 <= 0.0 ? num15 * 1.6 : num15 * 0.5;
        double num16 = f <= 0.0 ? Maths.Levelize2(f, 0.5) : Maths.Levelize3(f, 0.7);
        double num17 = simplexNoise2.Noise3DFBM(num1 * num * 2.5, num10 * num2 * 8.0, num11 * num3 * 2.5, 2) * 0.6 - 0.3;
        double num18 = f * num8 + num17 + num9;
        double num19 = num18 >= 1.0 ? (num18 - 1.0) * 0.8 + 1.0 : num18;
        double num20 = num16;
        data.heightData[i] = (ushort) (((double) this.planet.radius + num20) * 100.0);
      }));
    }

    public override void GenerateVeins(StarData star, GalaxyData galaxy, bool sketchOnly)
    {
      ThemeProto themeProto = LDB.themes.Select(this.planet.theme);
      if (themeProto == null)
        return;
      URandom1 urandom1_1 = new URandom1(this.planet.seed);
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      URandom1 urandom1_2 = new URandom1(urandom1_1.Next());
      PlanetRawData data = this.planet.data;
      float num1 = 2.1f / this.planet.radius;
      VeinProto[] veinProtos = PlanetModelingManager.veinProtos;
      int[] veinModelIndexs = PlanetModelingManager.veinModelIndexs;
      int[] veinModelCounts = PlanetModelingManager.veinModelCounts;
      int[] veinProducts = PlanetModelingManager.veinProducts;
      int[] numArray1 = new int[veinProtos.Length];
      float[] numArray2 = new float[veinProtos.Length];
      float[] numArray3 = new float[veinProtos.Length];
      if (themeProto.VeinSpot != null)
        Array.Copy((Array) themeProto.VeinSpot, 0, (Array) numArray1, 1, Math.Min(themeProto.VeinSpot.Length, numArray1.Length - 1));
      if (themeProto.VeinCount != null)
        Array.Copy((Array) themeProto.VeinCount, 0, (Array) numArray2, 1, Math.Min(themeProto.VeinCount.Length, numArray2.Length - 1));
      if (themeProto.VeinOpacity != null)
        Array.Copy((Array) themeProto.VeinOpacity, 0, (Array) numArray3, 1, Math.Min(themeProto.VeinOpacity.Length, numArray3.Length - 1));
      float p = 1f;
      ESpectrType spectr = star.spectr;
      switch (star.type)
      {
        case EStarType.MainSeqStar:
          switch (spectr)
          {
            case ESpectrType.M:
              p = 2.5f;
              break;
            case ESpectrType.K:
              p = 1f;
              break;
            case ESpectrType.G:
              p = 0.7f;
              break;
            case ESpectrType.F:
              p = 0.6f;
              break;
            case ESpectrType.A:
              p = 1f;
              break;
            case ESpectrType.B:
              p = 0.4f;
              break;
            case ESpectrType.O:
              p = 1.6f;
              break;
          }
          break;
        case EStarType.GiantStar:
          p = 2.5f;
          break;
        case EStarType.WhiteDwarf:
          p = 3.5f;
          ++numArray1[9];
          ++numArray1[9];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.449999988079071; ++index)
            ++numArray1[9];
          numArray2[9] = 0.7f;
          numArray3[9] = 1f;
          ++numArray1[10];
          ++numArray1[10];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.449999988079071; ++index)
            ++numArray1[10];
          numArray2[10] = 0.7f;
          numArray3[10] = 1f;
          ++numArray1[12];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.5; ++index)
            ++numArray1[12];
          numArray2[12] = 0.7f;
          numArray3[12] = 0.3f;
          break;
        case EStarType.NeutronStar:
          p = 4.5f;
          ++numArray1[14];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.649999976158142; ++index)
            ++numArray1[14];
          numArray2[14] = 0.7f;
          numArray3[14] = 0.3f;
          break;
        case EStarType.BlackHole:
          p = 5f;
          ++numArray1[14];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.649999976158142; ++index)
            ++numArray1[14];
          numArray2[14] = 0.7f;
          numArray3[14] = 0.3f;
          break;
      }
      for (int index1 = 0; index1 < themeProto.RareVeins.Length; ++index1)
      {
        int rareVein = themeProto.RareVeins[index1];
        float num2 = star.index != 0 ? themeProto.RareSettings[index1 * 4 + 1] : themeProto.RareSettings[index1 * 4];
        float rareSetting1 = themeProto.RareSettings[index1 * 4 + 2];
        float rareSetting2 = themeProto.RareSettings[index1 * 4 + 3];
        float num3 = 1f - Mathf.Pow(1f - num2, p);
        float num4 = 1f - Mathf.Pow(1f - rareSetting2, p);
        if (urandom1_1.NextDouble() < (double) num3)
        {
          ++numArray1[rareVein];
          numArray2[rareVein] = num4;
          numArray3[rareVein] = num4;
          for (int index2 = 1; index2 < 12 && urandom1_1.NextDouble() < (double) rareSetting1; ++index2)
            ++numArray1[rareVein];
        }
      }
      float resourceCoef = star.resourceCoef;
      if (galaxy.birthPlanetId == this.planet.id)
        resourceCoef *= 0.6666667f;
      float num5 = 1f * 1.1f;
      Vector3[] vector3Array = new Vector3[512];
      EVeinType[] eveinTypeArray = new EVeinType[512];
      int length = 0;
      Vector3 vector3_1;
      if (galaxy.birthPlanetId == this.planet.id)
      {
        Pose pose = this.planet.PredictPose(120.0);
        vector3_1 = (Vector3) Maths.QInvRotateLF(pose.rotation, star.uPosition - (VectorLF3) pose.position * 40000.0);
        vector3_1.Normalize();
        vector3_1 *= 0.75f;
      }
      else
      {
        Vector3 vector3_2;
        vector3_2.x = (float) (urandom1_2.NextDouble() * 2.0 - 1.0);
        vector3_2.y = (float) urandom1_2.NextDouble() - 0.5f;
        vector3_2.z = (float) (urandom1_2.NextDouble() * 2.0 - 1.0);
        vector3_2.Normalize();
        vector3_1 = vector3_2 * (float) (urandom1_2.NextDouble() * 0.4 + 0.2);
      }
      this.planet.veinSpotsSketch = numArray1;
      if (sketchOnly)
        return;
      for (int index3 = 1; index3 < 15 && length < vector3Array.Length; ++index3)
      {
        EVeinType eveinType = (EVeinType) index3;
        int num6 = numArray1[index3];
        if (num6 > 1)
          num6 += urandom1_2.Next(-1, 2);
        for (int index4 = 0; index4 < num6; ++index4)
        {
          int num7 = 0;
          Vector3 zero = Vector3.zero;
          bool flag1 = false;
          while (num7++ < 200)
          {
            zero.x = (float) (urandom1_2.NextDouble() * 2.0 - 1.0);
            zero.y = (float) (urandom1_2.NextDouble() * 2.0 - 1.0);
            zero.z = (float) (urandom1_2.NextDouble() * 2.0 - 1.0);
            if (eveinType != EVeinType.Oil)
              zero += vector3_1;
            zero.Normalize();
            if (eveinType != EVeinType.Bamboo || (double) data.QueryHeight(zero) <= (double) this.planet.realRadius - 4.0)
            {
              bool flag2 = false;
              float num8 = eveinType != EVeinType.Oil ? 196f : 100f;
              for (int index5 = 0; index5 < length; ++index5)
              {
                if ((double) (vector3Array[index5] - zero).sqrMagnitude < (double) num1 * (double) num1 * (double) num8)
                {
                  flag2 = true;
                  break;
                }
              }
              if (!flag2)
              {
                flag1 = true;
                break;
              }
            }
          }
          if (flag1)
          {
            vector3Array[length] = zero;
            eveinTypeArray[length] = eveinType;
            ++length;
            if (length == vector3Array.Length)
              break;
          }
        }
      }
      Array.Clear((Array) this.planet.veinAmounts, 0, this.planet.veinAmounts.Length);
      data.veinCursor = 1;
      this.planet.veinGroups = new PlanetData.VeinGroup[length];
      List<Vector2> vector2List = new List<Vector2>(100);
      VeinData vein = new VeinData();
      for (int index6 = 0; index6 < length; ++index6)
      {
        vector2List.Clear();
        Vector3 normalized = vector3Array[index6].normalized;
        EVeinType eveinType = eveinTypeArray[index6];
        int index7 = (int) eveinType;
        Quaternion rotation = Quaternion.FromToRotation(Vector3.up, normalized);
        Vector3 vector3_3 = rotation * Vector3.right;
        Vector3 vector3_4 = rotation * Vector3.forward;
        this.planet.veinGroups[index6].type = eveinType;
        this.planet.veinGroups[index6].pos = normalized;
        this.planet.veinGroups[index6].count = 0;
        this.planet.veinGroups[index6].amount = 0L;
        vector2List.Add(Vector2.zero);
        int num9 = Mathf.RoundToInt(numArray2[index7] * (float) urandom1_2.Next(20, 25));
        if (eveinType == EVeinType.Oil)
          num9 = 1;
        int num10 = 0;
        while (num10++ < 20)
        {
          int count = vector2List.Count;
          for (int index8 = 0; index8 < count && vector2List.Count < num9; ++index8)
          {
            if ((double) vector2List[index8].sqrMagnitude <= 36.0)
            {
              double num11 = urandom1_2.NextDouble() * Math.PI * 2.0;
              Vector2 vector2_1 = new Vector2((float) Math.Cos(num11), (float) Math.Sin(num11));
              vector2_1 += vector2List[index8] * 0.2f;
              vector2_1.Normalize();
              Vector2 vector2_2 = vector2List[index8] + vector2_1;
              bool flag = false;
              for (int index9 = 0; index9 < vector2List.Count; ++index9)
              {
                if ((double) (vector2List[index9] - vector2_2).sqrMagnitude < 0.850000023841858)
                {
                  flag = true;
                  break;
                }
              }
              if (!flag)
                vector2List.Add(vector2_2);
            }
          }
          if (vector2List.Count >= num9)
            break;
        }
        int num12 = Mathf.RoundToInt(numArray3[index7] * 100000f * resourceCoef);
        if (num12 < 20)
          num12 = 20;
        int num13 = num12 >= 16000 ? 15000 : Mathf.FloorToInt((float) num12 * (15f / 16f));
        int minValue = num12 - num13;
        int maxValue = num12 + num13 + 1;
        for (int index10 = 0; index10 < vector2List.Count; ++index10)
        {
          Vector3 vector3_5 = (vector2List[index10].x * vector3_3 + vector2List[index10].y * vector3_4) * num1;
          vein.type = eveinType;
          vein.groupIndex = (short) index6;
          vein.modelIndex = (short) urandom1_2.Next(veinModelIndexs[index7], veinModelIndexs[index7] + veinModelCounts[index7]);
          vein.amount = Mathf.RoundToInt((float) urandom1_2.Next(minValue, maxValue) * num5);
          if (this.planet.veinGroups[index6].type != EVeinType.Oil)
            vein.amount = Mathf.RoundToInt((float) vein.amount);
          if (vein.amount < 1)
            vein.amount = 1;
          vein.productId = veinProducts[index7];
          vein.pos = normalized + vector3_5;
          vein.minerCount = 0;
          float num14 = data.QueryHeight(vein.pos);
          data.EraseVegetableAtPoint(vein.pos);
          vein.pos = vein.pos.normalized * num14;
          this.planet.veinAmounts[(int) eveinType] += (long) vein.amount;
          ++this.planet.veinGroups[index6].count;
          this.planet.veinGroups[index6].amount += (long) vein.amount;
          data.AddVeinData(vein);
        }
      }
      vector2List.Clear();
    }

    public override void GenerateVeins(StarData star, GalaxyData galaxy)
    {
      ThemeProto themeProto = LDB.themes.Select(this.planet.theme);
      if (themeProto == null)
        return;
      URandom1 urandom1_1 = new URandom1(this.planet.seed);
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      urandom1_1.Next();
      VeinProto[] veinProtos = PlanetModelingManager.veinProtos;
      int[] numArray1 = new int[veinProtos.Length];
      if (themeProto.VeinSpot != null)
        Array.Copy((Array) themeProto.VeinSpot, 0, (Array) numArray1, 1, Math.Min(themeProto.VeinSpot.Length, numArray1.Length - 1));
      float p = 1f;
      ESpectrType spectr = star.spectr;
      switch (star.type)
      {
        case EStarType.MainSeqStar:
          switch (spectr)
          {
            case ESpectrType.M:
              p = 2.5f;
              break;
            case ESpectrType.K:
              p = 1f;
              break;
            case ESpectrType.G:
              p = 0.7f;
              break;
            case ESpectrType.F:
              p = 0.6f;
              break;
            case ESpectrType.A:
              p = 1f;
              break;
            case ESpectrType.B:
              p = 0.4f;
              break;
            case ESpectrType.O:
              p = 1.6f;
              break;
          }
          break;
        case EStarType.GiantStar:
          p = 2.5f;
          break;
        case EStarType.WhiteDwarf:
          p = 3.5f;
          ++numArray1[9];
          ++numArray1[9];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.449999988079071; ++index)
            ++numArray1[9];
          ++numArray1[10];
          ++numArray1[10];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.449999988079071; ++index)
            ++numArray1[10];
          ++numArray1[12];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.5; ++index)
            ++numArray1[12];
          break;
        case EStarType.NeutronStar:
          p = 4.5f;
          ++numArray1[14];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.649999976158142; ++index)
            ++numArray1[14];
          break;
        case EStarType.BlackHole:
          p = 5f;
          ++numArray1[14];
          for (int index = 1; index < 12 && urandom1_1.NextDouble() < 0.649999976158142; ++index)
            ++numArray1[14];
          break;
      }
      for (int index1 = 0; index1 < themeProto.RareVeins.Length; ++index1)
      {
        int rareVein = themeProto.RareVeins[index1];
        float num2 = star.index != 0 ? themeProto.RareSettings[index1 * 4 + 1] : themeProto.RareSettings[index1 * 4];
        float rareSetting1 = themeProto.RareSettings[index1 * 4 + 2];
        float num3 = 1f - Mathf.Pow(1f - num2, p);
        if (urandom1_1.NextDouble() < (double) num3)
        {
          ++numArray1[rareVein];
          for (int index2 = 1; index2 < 12 && urandom1_1.NextDouble() < (double) rareSetting1; ++index2)
            ++numArray1[rareVein];
        }
      }
      this.planet.veinSpotsSketch = numArray1;
    }
  }
}
